﻿using System;

namespace PortableTPL
{
    public class TaskFactory
    {
        readonly static TaskScheduler standardScheduler = new StandardTaskScheduler();

        internal static TaskScheduler StandardScheduler
        {
            get { return standardScheduler; }
        }

        public Task StartNew(Action action, CancellationToken token, TaskScheduler scheduler = null)
        {
            Task task = new Task(action, token);

            Schedule(scheduler, task);

            return task;
        }

        public Task StartNew(Action<object> action, object state, CancellationToken token, TaskScheduler scheduler = null)
        {
            Task task = new Task(action, state, token);

            Schedule(scheduler, task);

            return task;
        }

        public Task StartNew(Action action, TaskScheduler scheduler = null)
        {
            Task task = new Task(action);

            Schedule(scheduler, task);

            return task;
        }

        public Task StartNew(Action<object> action, object state, TaskScheduler scheduler = null)
        {
            Task task = new Task(action, state);

            Schedule(scheduler, task);

            return task;
        }

        public Task<T> StartNew<T>(Func<T> func, CancellationToken token, TaskScheduler scheduler = null)
        {
            Task<T> task = new Task<T>(func, token);

            Schedule(scheduler, task);

            return task;
        }

        public Task<T> StartNew<T>(Func<object, T> func, object state, CancellationToken token, TaskScheduler scheduler = null)
        {
            Task<T> task = new Task<T>(func, state, token);

            Schedule(scheduler, task);

            return task;
        }

        public Task<T> StartNew<T>(Func<T> func, TaskScheduler scheduler = null)
        {
            Task<T> task = new Task<T>(func);

            Schedule(scheduler, task);

            return task;
        }

        public Task<T> StartNew<T>(Func<object, T> func, object state, TaskScheduler scheduler = null)
        {
            Task<T> task = new Task<T>(func, state);

            Schedule(scheduler, task);

            return task;
        }

        public void ContinueWhenAll(Task[] tasks, Action<Task[]> action)
        {
            Task.WaitAll(tasks);
            action(tasks);
        }

        static void Schedule(TaskScheduler scheduler, Task task)
        {
            if (scheduler == null)
                StandardScheduler.EnqueueTask(task);
            else
                scheduler.EnqueueTask(task);
        }
    }
}
